commonlibsse_ng\re\b/
BSTEvent.rs

1use core::ptr::NonNull;
2
3use crate::re::BSAtomic::BSSpinLock;
4use crate::re::BSTArray::BSTArray;
5
6/// Represents the event notification control, mapping to the C++ enum.
7#[commonlibsse_ng_derive_internal::ffi_enum]
8#[repr(u8)]
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub enum BSEventNotifyControl {
11    Continue = 0,
12    Stop = 1,
13}
14
15#[derive(Debug)]
16pub struct BSTEventSink<Event> {
17    pub vtable: Option<NonNull<BSTEventSinkVtbl<Event>>>,
18}
19const _: () = assert!(core::mem::size_of::<BSTEventSink<*mut ()>>() == 0x8);
20
21impl<Event> BSTEventSink<Event> {
22    /// # Safety
23    pub unsafe fn process_event(
24        &mut self,
25        event: *const Self,
26        event_source: *const BSTEventSource<Event>,
27    ) -> BSEventNotifyControl {
28        self.vtable
29            .map(|ptr| unsafe { ptr.as_ref() })
30            .and_then(|vtable| {
31                unsafe { (vtable.ProcessEvent)(self, event, event_source) }.to_enum()
32            })
33            .unwrap_or(BSEventNotifyControl::Stop)
34    }
35}
36
37pub struct BSTEventSinkVtbl<Event> {
38    /// C++ destructor `~BSTEventSink`
39    pub CxxDrop: unsafe extern "C" fn(this: *mut BSTEventSink<Event>),
40
41    pub ProcessEvent: unsafe extern "C" fn(
42        this: *mut BSTEventSink<Event>,
43        event: *const BSTEventSink<Event>,
44        eventSource: *const BSTEventSource<Event>,
45    ) -> BSEventNotifyControl_CEnum,
46}
47
48#[repr(C)]
49#[derive(Debug)]
50pub struct BSTEventSource<Event> {
51    pub sinks: BSTArray<*mut BSTEventSink<Event>>,
52    pub pendingRegisters: BSTArray<*mut BSTEventSink<Event>>,
53    pub pendingUnregisters: BSTArray<*mut BSTEventSink<Event>>,
54    pub lock: BSSpinLock,
55    pub notifying: bool,
56    pub pad51: u8,
57    pub pad52: u16,
58    pub pad54: u32,
59}
60const _: () = {
61    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, sinks) == 0x00);
62    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, pendingRegisters) == 0x18);
63    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, pendingUnregisters) == 0x30);
64    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, lock) == 0x48);
65    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, notifying) == 0x50);
66    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, pad51) == 0x51);
67    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, pad52) == 0x52);
68    assert!(core::mem::offset_of!(BSTEventSource<*mut ()>, pad54) == 0x54);
69
70    assert!(core::mem::size_of::<BSTEventSource<*mut ()>>() == 0x58);
71};
72
73impl<Event> BSTEventSource<Event> {
74    #[inline]
75    pub const fn new() -> Self {
76        Self {
77            sinks: BSTArray::new(),
78            pendingRegisters: BSTArray::new(),
79            pendingUnregisters: BSTArray::new(),
80            lock: BSSpinLock::new(),
81            notifying: false,
82            pad51: 0,
83            pad52: 0,
84            pad54: 0,
85        }
86    }
87
88    pub fn add_event_sink(&mut self, sink: *mut BSTEventSink<Event>) {
89        let _guard = self.lock.lock();
90
91        if sink.is_null() {
92            return;
93        }
94
95        if self.notifying {
96            if !self.pendingRegisters.contains(&sink) {
97                self.pendingRegisters.push(sink);
98            }
99        } else if !self.sinks.contains(&sink) {
100            self.sinks.push(sink);
101        }
102
103        self.pendingUnregisters.retain(|&s| s != sink);
104    }
105
106    pub fn remove_event_sink(&mut self, sink: *mut BSTEventSink<Event>) {
107        let _guard = self.lock.lock();
108
109        if self.notifying {
110            if !self.pendingUnregisters.contains(&sink) {
111                self.pendingUnregisters.push(sink);
112            }
113        } else {
114            self.sinks.retain(|&s| s != sink);
115        }
116
117        self.pendingUnregisters.retain(|&s| s != sink);
118    }
119
120    /// # Safety
121    pub unsafe fn send_event(&mut self, event: *const BSTEventSink<Event>) {
122        let _guard = self.lock.lock();
123
124        let was_notifying = self.notifying;
125        self.notifying = true;
126
127        if !was_notifying && !self.pendingRegisters.is_empty() {
128            for sink in self.pendingRegisters.drain(..) {
129                if !self.sinks.contains(&sink) {
130                    self.sinks.push(sink);
131                }
132            }
133        }
134
135        for sink in self.sinks.iter() {
136            let ret = unsafe { (**sink).process_event(event, self) };
137            if !self.pendingUnregisters.contains(sink) && ret == BSEventNotifyControl::Stop {
138                break;
139            }
140        }
141
142        self.notifying = was_notifying;
143
144        if !was_notifying && !self.pendingUnregisters.is_empty() {
145            for sink in self.pendingUnregisters.drain(..) {
146                self.sinks.retain(|&s| s != sink);
147            }
148        }
149    }
150}
151
152impl<Event> Default for BSTEventSource<Event> {
153    #[inline]
154    fn default() -> Self {
155        Self::new()
156    }
157}